UNPKG

nhfs

Version:

NHFS — A sleek HTTP file server for the web built with Next.js and HeroUI. (Alpha)

60 lines (48 loc) 1.71 kB
import { createReadStream, statSync } from 'fs'; import { NextRequest } from 'next/server'; import mime from 'mime-types'; import { getData, convertParams } from '@/lib/io'; import { BASE_DIR } from '@/env'; export async function GET( req: NextRequest, { params }: { params: Promise<{ file: string[] }> }, ) { const { file } = await params; const result = await getData(file); if (!result.ok) { if (result.error.code === 'ENOENT') { return new Response('Not Found', { status: 404 }); } if (result.error.code === 'EACCES') { return new Response('Forbidden', { status: 403 }); } return new Response('Internal Server Error', { status: 500 }); } // Directory listing as JSON if (result.value.type === 'dir') { return Response.json(result.value); } // File serving const relPath = convertParams(file); const filePath = require('path').resolve(BASE_DIR, relPath); // Check again for permissions if (result.value.permissions === 'EACCES') { return new Response('Forbidden', { status: 403 }); } // Stream file try { const stat = statSync(filePath); const mimeType = mime.lookup(filePath) || 'application/octet-stream'; const headers = new Headers({ 'Content-Type': mimeType, 'Content-Length': stat.size.toString(), 'Last-Modified': stat.mtime.toUTCString(), 'Cache-Control': 'public, max-age=31536000', // 1 year 'Content-Disposition': `inline; filename="${encodeURIComponent(result.value.name)}"`, }); // @ts-ignore return new Response(createReadStream(filePath), { status: 200, headers }); } catch (err) { return new Response('Internal Server Error', { status: 500 }); } }